package com.onpositive.mediawiki.dataminer;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

import storage.v1.CategoryStorage;

import com.onpositive.data.IPropertyConstants;
import com.onpositive.dataminer.core.DefaultUniverse;
import com.onpositive.dataminer.core.ICanExtractImages;
import com.onpositive.knowledge.model.ICanBeActual;
import com.onpositive.knowledge.model.IHasUniverse;
import com.onpositive.knowledge.model.IThing;
import com.onpositive.knowledge.model.IType;
import com.onpositive.knowledge.model.IUniverse;
import com.onpositive.knowledge.model.values.DescribedValue;
import com.onpositive.knowledge.model.values.IHasValue;
import com.onpositive.mediawiki.propertyparser.ParsedDocument;
import com.onpositive.semantic.model.api.property.IHasPropertyProvider;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.semantic.model.api.property.IPropertyProvider;
import com.onpositive.semantic.model.api.property.PropertyAccess;
import com.onpositive.semantic.model.api.realm.IRealm;
import com.onpositive.semantic.model.api.realm.Realm;
import com.onpositive.semantic.model.ui.generic.IKnowsImageObject;
import com.onpositive.units.ParsedFileList;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.TextContent;
import com.onpositive.wikistorage.PictureManager;

public class WikiThing implements IThing, IType, IKnowsImageObject, ICanBeActual, Serializable, IHasUniverse{

	/**
	 * 
	 */
	private static final long serialVersionUID = 947283619584220327L;
	protected String name;
	
	transient MediaWikiUniverse parentUniverse;

	public WikiThing(String s, MediaWikiUniverse universe) {
		this.name = s;
		this.parentUniverse = universe;

	}

	Collection<IHasValue> getTextContent() {
		IProperty prop = DefaultUniverse.getInstance().getProperty( this, IPropertyConstants.TEXT_CONTENT_PROPERTY_NAME );
		Object o1 = prop.getValue( this ) ;
		if( ! ( o1 instanceof DescribedValue ) )
			return null ;
		
		DescribedValue dval = (DescribedValue) o1 ;
		
		Object o2 = dval.value() ;
		
		if( !(o2 instanceof TextContent) )
			return null ;
		
		TextContent tc = (TextContent) o2 ;
		
		Collection<IHasValue> col = (Collection<IHasValue>) tc.value() ;
		return col ;		
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		WikiThing other = (WikiThing) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equalsIgnoreCase(other.name))
			return false;
		return true;
	}
	
	public void extractImages(){
		Collection<IUniverse> subUniverses = DefaultUniverse.getInstance().getSubUniverses();
		for (IUniverse l:subUniverses){
			if (l instanceof ICanExtractImages){
				ICanExtractImages km= (ICanExtractImages) l;
				km.extractImages();
			}
		}
	//	getBinding().refresh();
	}	

	public String getRawText() {
		return parentUniverse.getRawText(name);
	}

	@Override
	public String getId() {
		return name;
	}

	@Override
	public IRealm<IType> getTypes() {
		
		Realm<IType> tpe = new Realm<IType>();
		
		Collection<String> parentCategoryNames = parentUniverse
				.getParents(name);
		if (parentCategoryNames == null) {
			parentCategoryNames = new HashSet<String>();
		}
		for (String s : parentCategoryNames) {
			tpe.add(new WikiThing(s, parentUniverse));
		}
		return tpe;
	}

	@Override
	public IRealm<IType> getSuperTypes() {
		return getTypes();
	}

	@Override
	public String toString() {
		return name;
	}

	@Override
	public String getImageID() {
		Collection<String> children = parentUniverse.getChildren(name);
		if (children == null || children.isEmpty()) {
			return "com.onpositive.mediawiki.crawler.image5";
		}
		return "com.onpositive.mediawiki.crawler.category";
	}

	public Object getPictureList() {
		IProperty property = DefaultUniverse.getInstance().getProperty(this,
				IPropertyConstants.PICTURE_LIST_PROPERTY_NAME);
		if (property != null) {
			Object value = property.getValue(this);
			if (value instanceof DescribedValue) {
				DescribedValue vl = (DescribedValue) value;
				value = vl.value();
			}
			if (value instanceof ParsedFileList) {
				ParsedFileList fl = (ParsedFileList) value;
				ArrayList<String> valuesList = fl.getValuesList();
				ArrayList<String> ts = new ArrayList<String>();
				if (valuesList != null)
					for (String s : valuesList) {
						// PictureManager instance =
						// PictureManager.getInstance(parentUniverse
						// .getRootPath());
						// String convertToLocalPath =
						// instance.convertToLocalPath(s,this.name);
						ts.add(s);

					}
				return ts;
			}
			return value;
		}
		return new ArrayList<String>();
	}

	public Object getDefaultImage() {
		IProperty property = DefaultUniverse.getInstance().getProperty(this,
				IPropertyConstants.EXTERNAL_DEFAULT_PICTURE_PROPERTY_NAME);
		if (property != null) {
			Object value = property.getValue(this);

			if (value != null) {
				value = new File(value.toString()).getAbsolutePath();
				String rootPath = parentUniverse.getRootPath();
				File fl=new File(rootPath);
				if (value.toString().startsWith(fl.getAbsolutePath())) {
					value = value.toString().substring(
							(fl.getAbsolutePath().length()+"pictures".length()+2+name.length()+1));
				}
				return value;
			}
			return value;
		}
		return null;
	}

	public Object getLongDefaultImage() {
		Object defaultImage = getDefaultImage();
		if (defaultImage != null) {
			PictureManager instance = PictureManager.getInstance(parentUniverse
					.getRootPath());
			boolean checkPicturePresence = instance.checkPicturePresence(
					defaultImage.toString(), name);
			if (!checkPicturePresence) {
				instance.grabPictureFromNet(defaultImage.toString(), name );
			}
			return instance.convertToLocalPath(defaultImage.toString(), name);

		}
		IProperty property = DefaultUniverse.getInstance().getProperty(this, IPropertyConstants.WWW_PICTURE_LINKS_PROPERTY_NAME);
		if (property!=null){
			Object value = property.getValue(this);
			if (value!=null){
			ParsedFileList value2 = (ParsedFileList) (((DescribedValue)value).value());
			ArrayList<String> valuesList = value2.getValuesList();
			for (final String s:valuesList){
				try{
				final PictureManager instance = PictureManager.getInstance(parentUniverse
						.getRootPath());
				boolean checkPicturePresence = instance.checkPicturePresence(
						s, name);
				if (!checkPicturePresence) {
					Thread sm=new Thread(){
						public void run() {
							instance.grabPictureFromNet(s.toString(), name );
						};
					};
					sm.start();
					sm.join(15000);
					
				}
				return instance.convertToLocalPath(s.toString(),name);
				}catch (Exception e) {
					e.printStackTrace();
					// TODO: handle exception
				}
			}
			}
		}
		return null;
	}

	public void setDefaultImage(Object im) {
		IProperty property = DefaultUniverse.getInstance().getProperty(this,
				IPropertyConstants.EXTERNAL_DEFAULT_PICTURE_PROPERTY_NAME);
		if (property != null) {
			//
			if (im != null) {
				// String convertToLocalPath = instance.convertToLocalPath(
				// im.toString(), name);
				PropertyAccess.setValue(property, this, im.toString());
			} else {
				PropertyAccess.setValue(property, this, null);
			}
		}

	}
	public void setActuality( boolean val )
	{
		ParsedDocument pd = parentUniverse.getParsedDocument( this.name ) ;
		if( pd != null )
			pd.setActual(val) ;		
	}
	
	public void reparse(){
		parentUniverse.reparse(name);
	}
	
	public void reload(){
		parentUniverse.reparse(name,CategoryStorage.FORCE_RELOAD_FLAG);
	}
	
	public void reparseAll(){
		parentUniverse.reparseAll();
	}
	
	public void setDepricated(boolean value){
		IProperty prop = DefaultUniverse.getInstance().getProperty(this,IPropertyConstants.ACTUALITY_PROPERTY_METADATA_ID ) ;
		PropertyAccess.setValue(prop, this, !value);
	}
	
	public boolean isDepricated(){
		
		IProperty prop = DefaultUniverse.getInstance().getProperty(this,IPropertyConstants.ACTUALITY_PROPERTY_METADATA_ID ) ;
		if (prop==null){
			return true;
		}
		Object val = prop.getValue( this ) ;
		if( val == null )
			return false ;
		if( val instanceof DescribedValue)
		{
			DescribedValue v=(DescribedValue) val;
			val=v.value();
		}
		if( val instanceof ParsedValue)
			val = ((ParsedValue)val).value() ;
		
		if( val instanceof Boolean )
			return !(Boolean)val ;
		
		if( val instanceof String )
			return !Boolean.parseBoolean( (String)val ) ;
		
		return false ;
		
//		if (DefaultUniverse.getInstance().getEnoughDataAuditResult().isSuspicios(this)){
//			return true;
//		}
//		return false;
	}
	 private void writeObject(java.io.ObjectOutputStream out) throws IOException
	 {
		 out.defaultWriteObject() ;
	 }
	 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
	 {
		 in.defaultReadObject() ;
	 }

	@Override
	public IUniverse getUniverse() {
		return parentUniverse;
	}

	@Override
	public void setUniverse(IUniverse universe) {
		
		if( parentUniverse instanceof MediaWikiUniverse )
			this.parentUniverse = (MediaWikiUniverse) parentUniverse;		
	}

	public void contributeStandart(IProperty property) {		
		parentUniverse.contributeStandard( this, property ) ;		
	}

	@Override
	public IProperty getProprty(String id) {
		return DefaultUniverse.getInstance().getProperty(this, id);
	}


}
